﻿/* $RCSFile: ImageMetadata.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/AddonNice.ImageSettings/UI/ImageMetadata.cs $
 * $log$
 * Revision 7 2010/08/09 09:44:02  christian.surieux
 *   Added Log to cs sources files
 */

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Globalization;

using AddonNice.Diagnostics;

using Trace2    =   System.Diagnostics.Trace;

namespace AddonNice.CRMImage.UI
{
    public class ImageMetaData
    {
        // Metadata format version
        public const int mVersion       =   2;
        protected XmlDocument Metadata  =   new XmlDocument();
        bool _Changed                   =   false;

        public bool Changed
        {
            get
            {
                return _Changed;
            }
        }
        public ImageMetaData()
        {
            CreateRoot();
        }

        public void CreateRoot()
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]ImageMetaData CreateRoot BEG.",ImageMetaDataTrace.Sw.Info);
            Metadata.AppendChild(Metadata.CreateElement("Metadata"));
            SetVersion();
        }

        public string OuterXml
        {
            get
            {
			    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( "[V]ImageMetaData  OuterXml Called.",ImageMetaDataTrace.Sw.Info);
                return Metadata.OuterXml;
            }
        }

        public int Version
        {
            get
            {
                return GetIntRootAttibute("MV");
            }
        }

        public void SetVersion()
        {
            CreateAttribute("MV",mVersion.ToString());
        }

        public void LoadXml(string MetadataXml)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData LoadXml BEG MetadataXml: '{0}'.", MetadataXml),ImageMetaDataTrace.Sw.Info);
            if ( !string.IsNullOrEmpty(MetadataXml) )
                Metadata.LoadXml(MetadataXml);
            // convert old versions
            if (Version < mVersion)
                Convert();
            else if (Root.SelectSingleNode("MV") != null && Root.SelectSingleNode("MV").InnerText == "2")
            {
                Convert2();
            }
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]ImageMetaData LoadXml END.",ImageMetaDataTrace.Sw.Info);
        }

        public void AddToRoot(string val)
        {
            XmlDocumentFragment docFrag =   Metadata.CreateDocumentFragment();
            try
            {
                docFrag.InnerXml = val;
            }
            catch (XmlException ex)
            {
                if ( ImageMetaDataTrace.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ImageMetaData AddToRoot ex: {0}.",ex),ImageMetaDataTrace.Sw.Info);
                throw;
            }
            Root.AppendChild(docFrag);
			// remove non element nodes like blankXmlNode
            for (int i=0 ; i < Root.ChildNodes.Count; i++)
			{
                XmlNode nd =    Root.ChildNodes[i];
                if (!(nd is XmlElement))
                {
		            if ( ImageMetaDataTrace.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData AddToRoot removing nd: {0}",nd.InnerText),ImageMetaDataTrace.Sw.Info);
                    Root.RemoveChild(nd);
                    i--;
                }
			}
        }
        
        /// <summary>
        /// The new val must be xml code, create a DocumentFragment with it and add as a new lement to root
        /// If flag is set to true, an existing element will be cleared of attributs and children before add
        /// </summary>
        public void AddToElement(string key,string val,bool clearNode)
        {
            XmlDocumentFragment docFrag =   Metadata.CreateDocumentFragment();
            try
            {
                docFrag.InnerXml = val;
            }
            catch (XmlException ex)
            {
		        if ( ImageMetaDataTrace.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ImageMetaData AddToElement ex: {0}.",ex),ImageMetaDataTrace.Sw.Info);
                throw;
            }
            XmlElement nd   =   GetElement(key,true);
            if ( clearNode )
                nd.RemoveAll();
            nd.AppendChild(docFrag);
			// remove non element nodes like blankXmlNode
            for (int i=0 ; i < nd.ChildNodes.Count; i++)
			{
                XmlNode nd2 =    nd.ChildNodes[i];
                if (!(nd2 is XmlElement))
                {
		            if ( ImageMetaDataTrace.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData AddToElement removing nd: {0}",nd2.InnerText),ImageMetaDataTrace.Sw.Info);
                    nd.RemoveChild(nd2);
                    i--;
                }
			}
        }

        /// <summary>
        /// The new val must be xml code, create a DocumentFragment with it and add as a new lement to root
        /// If flag is set to true, an existing element will be cleared of attributs and children before add
        /// </summary>
        public void MergeElement(string key,string val,bool clearNode)
        {
	        if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData MergeElement BEG key: {0}, val: {1}, clearNode: {2}.",
                    key,val,clearNode),ImageMetaDataTrace.Sw.Info);
            XmlDocumentFragment docFrag =   Metadata.CreateDocumentFragment();
            try
            {
                docFrag.InnerXml    =   val;
            }
            catch (XmlException ex)
            {
		        if ( ImageMetaDataTrace.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ImageMetaData MergeElement ex: {0}.",ex),ImageMetaDataTrace.Sw.Info);
                throw;
            }
            XmlElement nd           =   GetElement(key,true);
            if ( clearNode )
                nd.RemoveAll();
            XmlNode ndb             =   docFrag.SelectSingleNode(key);
	        if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData MergeElement ndb.InnerXml: {0}.",ndb.InnerXml),ImageMetaDataTrace.Sw.Info);
	        if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData MergeElement ndb.ChildNodes.Count: {0}.",ndb.ChildNodes.Count),ImageMetaDataTrace.Sw.Info);
            int i=0 ;
            while( ndb.ChildNodes.Count > 0)
            {
                XmlNode cnd         =   ndb.ChildNodes[0];
                nd.AppendChild(cnd);
            }
			// remove non element nodes like blankXmlNode
            for (i=0 ; i < nd.ChildNodes.Count; i++)
			{
                XmlNode nd2 =    nd.ChildNodes[i];
                if (!(nd2 is XmlElement))
                {
		            if ( ImageMetaDataTrace.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData MergeElement removing nd: {0}",nd2.InnerText),ImageMetaDataTrace.Sw.Info);
                    nd.RemoveChild(nd2);
                    i--;
                }
			}
        }

        /// <summary>
        /// The new val must be xml code, create a DocumentFragment with it and add as a new lement to root
        /// If flag is set to true, an existing element will be cleared of attributs and children before add
        /// </summary>
        public void AddElementToElement(string key,string key2,string val,bool clearNode)
        {
            XmlDocumentFragment docFrag =   Metadata.CreateDocumentFragment();
            try
            {
                docFrag.InnerXml = val;
            }
            catch (XmlException ex)
            {
		        if ( ImageMetaDataTrace.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ImageMetaData AddElementToElement ex: {0}.",ex),ImageMetaDataTrace.Sw.Info);
                throw;
            }
            XmlElement nd   =   GetElement(key,true);
            XmlElement nd1  =   (XmlElement)nd.SelectSingleNode(key2);
            if (nd1 != null)
            {
                if (clearNode)
                    nd1.RemoveAll();
            }
            else
            {
                nd1 =   CreateElement(key2);
                nd.AppendChild(nd1);
            }
            nd1.AppendChild(docFrag);
			// remove non element nodes like blankXmlNode
            for (int i=0 ; i < nd1.ChildNodes.Count; i++)
			{
                XmlNode nd2 =    nd1.ChildNodes[i];
                if (!(nd2 is XmlElement))
                {
		            if ( ImageMetaDataTrace.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData AddElementToElement removing nd: {0}",nd2.InnerText),ImageMetaDataTrace.Sw.Info);
                    nd1.RemoveChild(nd2);
                    i--;
                }
			}
        }

        public XmlAttribute CreateAttribute(string attName)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData CreateAttribute attName: {0}.", attName),ImageMetaDataTrace.Sw.Info);
            return Metadata.CreateAttribute(attName);
        }

        public XmlElement CreateElement(string elementName)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData CreateElement attName: {0}.", elementName),ImageMetaDataTrace.Sw.Info);
            return Metadata.CreateElement(elementName);
        }

        public XmlElement GetElement(string elementName, bool CreateIdNotFound)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetElement attName: {0}, CreateIdNotFound: {1}.", elementName,CreateIdNotFound),ImageMetaDataTrace.Sw.Info);
            XmlNode nd      =   Root.SelectSingleNode(elementName);
            if ( ( nd == null ) && CreateIdNotFound )
            {
                nd          =   Metadata.CreateElement(elementName);
                AppendElement((XmlElement)nd);
            }
            return  (XmlElement)nd;
        }
        
        public XmlElement GetElement(string elementName)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData CreateElement attName: {0}.", elementName),ImageMetaDataTrace.Sw.Info);
            return  (XmlElement)Root.SelectSingleNode(elementName);
        }
        
        public void AppendAttribute(XmlAttribute att)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData AppendAttribute att.Name: {0}.", att.Name),ImageMetaDataTrace.Sw.Info);
            Metadata.DocumentElement.Attributes.Append(att);
            _Changed                   =   true;
        }

        public void AppendElement(XmlElement element)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData AppendElement element.Name: {0}.", element.Name),ImageMetaDataTrace.Sw.Info);
            Metadata.DocumentElement.AppendChild(element);
            _Changed                   =   true;
        }

        public XmlNode Root
        {
            get
            {
                XmlNode nd  =   Metadata.DocumentElement.SelectSingleNode("/Metadata");
                if (nd == null)
                {
                    string msg  =   "[E]ImageMetaData Root GET null.";
                    if (ImageMetaDataTrace.Sw.TraceError)
                        Trace2.WriteLine(msg, ImageMetaDataTrace.Sw.Info);
                    throw new Exception(msg);
                }
                return nd;
            }
        }

        public XmlAttribute CreateAttribute(string attName,string Val)
        {
		    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData CreateAttribute attName: {0}, Val: {1}.", attName,Val),ImageMetaDataTrace.Sw.Info);
            XmlAttribute att    =   Metadata.CreateAttribute(attName);
            att.Value           =   Val;
            Metadata.DocumentElement.Attributes.Append(att);
            _Changed                   =   true;
            return att;
        }

        public XmlElement CreateElement(string elementName,string Val)
        {
	        if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData CreateElement elementName: {0}, Val: {1}.", elementName,Val),ImageMetaDataTrace.Sw.Info);
            return SetMetadata(elementName,Val);
        }

        public void CopyElements2Key(ImageMetaData md,string flKey)
        {
            XmlNode mr  =   md.Root;
            if ( mr.HasChildNodes )
                foreach (XmlElement nd in mr.ChildNodes)
                {
                    string val  =   md.GetMetadata(nd.Name);
		            if ( ImageMetaDataTrace.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData CopyElements nd.Name: {0}, val: {1}",nd.Name,val),ImageMetaDataTrace.Sw.Info);
                    SetMetadata(flKey,nd.Name,val);
                }
        }

        public int GetIntRootAttibute(string key)
        {
	        if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetIntRootAttibute key: {0}.", key),ImageMetaDataTrace.Sw.Info);
            string str  =   GetRootAttribute(key);
            if ( str == null )
                return 0;
            return int.Parse(str);
        }

        public string GetRootAttribute(string key)
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetRootAttribute key: {0}.", key),ImageMetaDataTrace.Sw.Info);
            XmlNode targetNode  = Root.SelectSingleNode("/Metadata/@" + key);
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetRootAttribute targetNode null: {0}.", targetNode == null),ImageMetaDataTrace.Sw.Info);
            if (targetNode == null)
                return null;
            string str          =   targetNode.Value;
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetRootAttribute targetNode.Value: {0}.",str),ImageMetaDataTrace.Sw.Info);
            return str;
        }

        public void SetRootAttribute(string key,string val,bool create)
        {
            XmlNode targetNode  = Root.SelectSingleNode("/Metadata/@" + key);
            if ( targetNode == null)
            {
                if (create)
                    targetNode  = Metadata.CreateAttribute(key);
                else return;
            }
            targetNode.Value    =   val;
            _Changed                   =   true;
        }

        public void Convert()
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert BEG OuterXml: '{0}'.", Metadata.OuterXml),ImageMetaDataTrace.Sw.Info);
            XmlDocument Metadata2   =   new XmlDocument();
            XmlNode Root2           =   Metadata2.CreateElement("Metadata");
            Metadata2.AppendChild(Root2);
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]ImageMetaData Convert Root2 Ok.", ImageMetaDataTrace.Sw.Info);
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert BEG HasAttributes: {0}.", Metadata.DocumentElement.HasAttributes),ImageMetaDataTrace.Sw.Info);
            if (Metadata.DocumentElement.HasAttributes )
            {
                if (ImageMetaDataTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert Metadata.DocumentElement.Attributes.Count: {0}.", Metadata.DocumentElement.Attributes.Count), ImageMetaDataTrace.Sw.Info);
                foreach (XmlAttribute att in Metadata.DocumentElement.Attributes)
                {
                    if (ImageMetaDataTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert att.Name: {0}, att.Value: '{1}'.", att.Name,att.Value), ImageMetaDataTrace.Sw.Info);
                    if ( att.Name == "MV" )
                        continue;
                    XmlElement element              =   Metadata2.CreateElement(att.Name);
                    XmlAttribute newAtt             =   Metadata2.CreateAttribute("Value");
                    newAtt.Value                    =   att.Value;
                    element.Attributes.Append(newAtt);
                    if (ImageMetaDataTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert element.Name: {0}, element.InnerText: '{1}'.", element.Name,att.Value), ImageMetaDataTrace.Sw.Info);
                    Root2.AppendChild(element);
                }
            }
            Metadata                =   Metadata2;
            SetVersion();
            _Changed                =   true;
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert END Metadata.Attributes.Count: {0}.", (Metadata.DocumentElement.HasAttributes) ? Metadata.DocumentElement.Attributes.Count:0),ImageMetaDataTrace.Sw.Info);
        }

        public void Convert2()
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert2 BEG OuterXml: '{0}'.", Metadata.OuterXml),ImageMetaDataTrace.Sw.Info);
            XmlDocument Metadata2   =   new XmlDocument();
            XmlNode Root2           =   Metadata2.CreateElement("Metadata");
            Metadata2.AppendChild(Root2);
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]ImageMetaData Convert2 Root2 Ok.", ImageMetaDataTrace.Sw.Info);
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert2 BEG HasChildNodes: {0}.", Metadata.DocumentElement.HasChildNodes),ImageMetaDataTrace.Sw.Info);
            if (Metadata.DocumentElement.HasChildNodes )
            {
                if (ImageMetaDataTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert Metadata.DocumentElement.ChildNodes.Count: {0}.", Metadata.DocumentElement.ChildNodes.Count), ImageMetaDataTrace.Sw.Info);
                foreach (XmlElement att in Metadata.DocumentElement.ChildNodes)
                {
                    if (ImageMetaDataTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert2 att.Name: {0}, att.Value: '{1}'.", att.Name,att.InnerText), ImageMetaDataTrace.Sw.Info);
                    if ( att.Name == "MV" )
                        continue;
                    XmlElement element              =   Metadata2.CreateElement(att.Name);
                    XmlAttribute newAtt             =   Metadata2.CreateAttribute("Value");
                    newAtt.Value                    =   att.InnerText;
                    element.Attributes.Append(newAtt);
                    if (ImageMetaDataTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert2 element.Name: {0}, element.InnerText: '{1}'.", element.Name,att.Value), ImageMetaDataTrace.Sw.Info);
                    Root2.AppendChild(element);
                }
            }
            Metadata                =   Metadata2;
            SetVersion();
            _Changed                =   true;
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData Convert2 END Metadata.ChildNodes.Count: {0}.", (Metadata.DocumentElement.HasChildNodes) ? Metadata.DocumentElement.ChildNodes.Count:0),ImageMetaDataTrace.Sw.Info);
        }

        public int GetIntMetadata(string key)
        {
            string str  =   GetMetadata(key);
            if ( str == null )
                return 0;
            return int.Parse(str);
        }

        public string GetMetadata(string key)
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetMetadata BEG key: '{0}'.", key),ImageMetaDataTrace.Sw.Info);
            XmlNode targetNode  =   Root.SelectSingleNode("/Metadata/" + key);
            if (targetNode == null)
            {
			    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetMetadata END targetNode null key: {0}.",key),ImageMetaDataTrace.Sw.Info);
                return null;
            }
            string str          =   string.Empty;
            if ( targetNode.Attributes.Count == 0 )
                str             =   targetNode.InnerText;
            else
            {
                XmlAttribute att =   targetNode.Attributes["Value"];
                if ( att != null )
                    str          =   targetNode.Attributes["Value"].Value;
            }
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetMetadata END key: '{0}', val: '{1}'.", key,str),ImageMetaDataTrace.Sw.Info);
            return str;
        }

        public XmlElement SetIntMetadata(string key, int data)
        {
            return SetMetadata(key,data.ToString());
        }
        
		public string GetMetadata(string key,string subKey)
		{
			XmlNode targetNode			= Metadata.SelectSingleNode(string.Format("/Metadata/{0}/{1}",key,subKey));
            if (targetNode == null)
            {
			    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetMetadata END targetNode null key: {0}, subKey: {1}.",key,subKey),ImageMetaDataTrace.Sw.Info);
                return null;
            }
            string str          =   targetNode.Attributes["Value"].Value;
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData GetMetadata END key: '{0}', subKey: '{1}', val: '{2}'.", key,subKey,str),ImageMetaDataTrace.Sw.Info);
            return str;
		}

        /// <summary>
        /// Store a value under the key in the metadata parameter
        /// </summary>
        public XmlElement SetMetadata(string key, string data)
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData SetMetadata BEG key: '{0}', val: '{1}'.", key,data),ImageMetaDataTrace.Sw.Info);
            XmlElement targetNode               =   (XmlElement)Root.SelectSingleNode(key);
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData SetMetadata targetNode null: {0}.", (targetNode==null)),ImageMetaDataTrace.Sw.Info);
            if ( targetNode == null )
            {
                targetNode                      =   Metadata.CreateElement(key);
                XmlAttribute newAtt             =   Metadata.CreateAttribute("Value");
                newAtt.Value                    =   data;
                targetNode.Attributes.Append(newAtt);
                Root.AppendChild(targetNode);
            }
            else
            {
			    if ( ImageMetaDataTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData SetMetadata targetNode.HasAttributes: {0}.", targetNode.HasAttributes),ImageMetaDataTrace.Sw.Info);
                if ( !targetNode.HasAttributes   )
                    targetNode.InnerText        =   data;
                else
                {
                    if ( targetNode.HasAttribute("Value")   )
                    {
                        XmlAttribute att        =   targetNode.Attributes["Value"];
                        att.Value               =   data;
                        }
                    else
                    {
                        targetNode.InnerText     =   data;
                    }
                }
            }
            _Changed                    =   true;
            return targetNode;
        }

        /// <summary>
        /// Store a value under the key/subkey in the metadata parameter
        /// </summary>
        public XmlElement SetMetadata(string key, string subKey, string data)
        {
			if ( ImageMetaDataTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ImageMetaData SetMetadata BEG key: '{0}', subkey:  '{1}', val: '{2}'.", key,subKey,data),ImageMetaDataTrace.Sw.Info);
            string strSubKey                    =   string.Format("/Metadata/{0}/{1}",key,subKey);
            XmlElement targetNode               =   (XmlElement)Root.SelectSingleNode(strSubKey);
            if ( targetNode == null )
            {
                XmlElement Node                 =   Metadata.CreateElement(key);
                Root.AppendChild(Node);
                targetNode                      =   Metadata.CreateElement(subKey);
                XmlAttribute newAtt             =   Metadata.CreateAttribute("Value");
                newAtt.Value                    =   data;
                targetNode.Attributes.Append(newAtt);
                Node.AppendChild(targetNode);
            }
            else
            {
                targetNode.Attributes["Value"].Value    =   data;
            }
            _Changed                    =   true;
            return targetNode;
        }
    }
}
